use std::time::Duration;

use base_data::channel::{event::ChannelEvent, ChannelState, CommandMsg};
use tools::{utils::gen_id::get_now_duration, ResultEx, ResultNull};
use tracing::{debug, trace, warn};

use crate::sip2::{
	dialog::{dialog::Dialog, sipdata::SipData, WAIT_REPEAT_TIME},
	SipDirection, SipMethod,
};

use super::{SipTimeOver, SipTransactionState, WaitSipMessage};

//对register做单独操作. 不在这里进行
#[inline]
pub fn start_tran(dialog: &mut Dialog) {
	dialog.set_tran_state(SipTransactionState::Completed);
	dialog.start_time = get_now_duration();
	dialog.wait_resp_method = WaitSipMessage::None;
	dialog.retry_time = Duration::ZERO;
	dialog.over_time = SipTimeOver::Finish(WAIT_REPEAT_TIME);

	// 直接返回 200.并且跳至Complated
	let buf = dialog.generate_receive(&dialog.sip_data);
	dialog.send_to_remote(buf);

	handle_rev_sip_data(dialog);
}

///收到相应消息的处理,向业务逻辑发送,等待业务逻辑处理
#[inline]
fn handle_rev_sip_data(dialog: &mut Dialog) {
	match dialog.sip_data.direction {
		SipDirection::Request(SipMethod::Bye) => {
			dialog.send_to_business(ChannelEvent::ChannelHangup(
				dialog.id,
				dialog.sip_data.to_hangup_reason(),
			));
			dialog.send_to_business(ChannelEvent::ChannelCallState(
				dialog.id,
				ChannelState::Hangup,
			));
		}
		SipDirection::Request(SipMethod::Update) => warn!("收到update消息,目前未处理"),
		SipDirection::Request(_) => trace!("收到不处理的消息.{:?}", dialog.sip_data),
		SipDirection::Response(_) => {
			let b = dialog.sip_data.generate_call_not_exist();
			dialog.send_to_remote(b);
		}
	}
}

///处理事务收到的传输层的消息
#[inline]
pub fn handle_tran_msg(dialog: &mut Dialog, sip_data: SipData) -> ResultNull {
	match sip_data.direction {
		//在过程中再次收到请求.代表自己慢了.回复100.进入处理阶段
		SipDirection::Request(_) if sip_data.data == dialog.sip_data.data => {
			dialog.retry_send()?;
		}

		_ => debug!("no_inv_serv 收到无效请求."),
	}

	Ok(())
}

///处理事务收到的命令消息
#[inline]
pub fn handle_command_msg(_dialog: &mut Dialog, _cmd_msg: CommandMsg) -> ResultNull {
	Ok(())
}

///处理事务结束的操作..
/// 返回true表示事务结束时dialog同时结束.
#[inline]
pub fn end_tran(dialog: &mut Dialog) -> ResultEx<bool> {
	dialog.last_send_bytes = None;
	//目前来看非inv事务没有保存dialog的必要
	Ok(true)
}

#[inline]
pub fn handle_time_over(dialog: &mut Dialog, _to: SipTimeOver) -> ResultNull {
	//超时直接结束
	dialog.set_tran_state(SipTransactionState::Terminated);

	Ok(())
}
